package com.techshinogongjian.fp.util;

import com.techshinogongjian.fingerprint.TCFP;

public class FpImage {

	private static final String TAG = FpImage.class.getSimpleName();

	public byte[] mBmpImgBuf;
	public long mOpBmpImgLen = 1;

	private static int[] sImageAttr;
	public static int sImgWidth;
	public static int sImgHeight;

	public static void setImageAttr(int[] imageAttr) {
		sImageAttr = imageAttr;
	}

	public byte[] getBmpImgBuf() {
		return mBmpImgBuf;
	}

	public void setBmpImgBuf(byte[] bmpImgBuf) {
		mBmpImgBuf = bmpImgBuf;
	}

	public long getOpBmpImgLen() {
		return mOpBmpImgLen;
	}

	public void setOpBmpImgLen(long opBmpImgLen) {
		mOpBmpImgLen = opBmpImgLen;
	}

	class BITMAPFILEHEADER {
		short bfType;// 2
		int bfSize;// 4
		short bfReserved1;// 2
		short bfReserved2;// 2
		int bfOffBits;// 4
	};

	class BITMAPINFOHEADER {
		int biSize; // 4
		int biWidth;// 8
		int biHeight;// 8
		short biPlanes;// 2
		short biBitCount;// 2
		int biCompression;// 4
		int biSizeImage;// 4
		long biXPelsPerMeter;// 8
		long biYPelsPerMeter;// 8
		int biClrUsed;// 4
		int biClrImportant;// 4
	};

	class RGBQUAD {
		byte rgbBlue;
		byte rgbGreen;
		byte rgbRed;
		byte rgbReserved;
	};

	/** 16位int转byte[] */
	public static byte[] short2byte(short res) {
		byte[] targets = new byte[2];
		targets[0] = (byte) (res & 0xff);// 最低位
		targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
		return targets;
	}

	/** 32位int转byte[] */
	public static byte[] int2byte(int res) {
		byte[] targets = new byte[4];
		targets[0] = (byte) (res & 0xff);// 最低位
		targets[1] = (byte) ((res >> 8) & 0xff);// 次低位
		targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
		targets[3] = (byte) (res >>> 24);// 最高位,无符号右移。
		return targets;
	}

	/** 64位int转byte[] */
	public static byte[] long2byte(long res) {
		byte[] targets = new byte[8];
		targets[0] = (byte) (res & 0xff);// 最低位
		targets[1] = (byte) ((res >> 8) & 0xff);// 次高位
		targets[2] = (byte) ((res >> 16) & 0xff);// 次高位
		targets[3] = (byte) ((res >> 24) & 0xff);// 次低位
		targets[4] = (byte) ((res >> 32) & 0xff);// 次高位
		targets[5] = (byte) ((res >> 40) & 0xff);// 次低位
		targets[6] = (byte) ((res >> 48) & 0xff);// 次高位
		targets[7] = (byte) (res >>> 56);// 最高位,无符号右移。

		return targets;
	}

	public int saveRawAsBmpBuf(byte[] pRawImgBuf, int iWidth, int iHeight) {
		// printk(KERN_ALERT"SaveRawAsBmp--\n");
		Logs.v("SaveRawAsBmp--\n");
		byte[] pBmpImgBuf = new byte[pRawImgBuf.length + 14 + 44 + 1024];
		BITMAPFILEHEADER fileHdr = new BITMAPFILEHEADER(); /* bmp文件头 14字节 */
		BITMAPINFOHEADER infoHdr = new BITMAPINFOHEADER(); /* bmp信息头 40字节 */
		int dwWide = (int) (iWidth - iWidth % 4);
		int dwHigh = (int) (iHeight - iHeight % 4);
		int dwSize = dwWide * dwHigh;
		int i;
		/* 填充BMP文件头的结构体，共5个成员，14个字节 */
		fileHdr.bfType = 19778; /* 彩图无调色板 */
		fileHdr.bfOffBits = 14 + 44 + 1024;
		fileHdr.bfSize = fileHdr.bfOffBits + dwSize;
		fileHdr.bfReserved1 = fileHdr.bfReserved2 = 0;

		/* 填充BMP信息头的结构体，共11个成员，56个字节 */
		infoHdr.biSize = 44;
		infoHdr.biWidth = dwWide;
		infoHdr.biHeight = dwHigh;
		infoHdr.biPlanes = 1;
		infoHdr.biBitCount = 8; /* 8位灰度图 */
		infoHdr.biCompression = 0;
		infoHdr.biSizeImage = dwSize;

		infoHdr.biClrUsed = 0;
		infoHdr.biClrImportant = 0;
		/* 8位的灰度图像需要填充调色板数组 */

		/* 填充BMP文件头的结构体，共5个成员，14个字节 */
		System.arraycopy(short2byte(fileHdr.bfType), 0, pBmpImgBuf, 0, 2);
		System.arraycopy(int2byte(fileHdr.bfSize), 0, pBmpImgBuf, 2, 4);
		System.arraycopy(short2byte(fileHdr.bfReserved1), 0, pBmpImgBuf, 6, 2);
		System.arraycopy(short2byte(fileHdr.bfReserved2), 0, pBmpImgBuf, 8, 2);
		System.arraycopy(int2byte(fileHdr.bfOffBits), 0, pBmpImgBuf, 10, 4);

		/* 填充BMP信息头的结构体，共11个成员，40个字节 */
		System.arraycopy(int2byte(infoHdr.biSize), 0, pBmpImgBuf, 14, 4);
		System.arraycopy(int2byte(infoHdr.biWidth), 0, pBmpImgBuf, 18, 4);
		System.arraycopy(int2byte(infoHdr.biHeight), 0, pBmpImgBuf, 22, 4);
		System.arraycopy(short2byte(infoHdr.biPlanes), 0, pBmpImgBuf, 26, 2);
		System.arraycopy(short2byte(infoHdr.biBitCount), 0, pBmpImgBuf, 28, 2);
		System.arraycopy(int2byte(infoHdr.biCompression), 0, pBmpImgBuf, 30, 4);
		System.arraycopy(int2byte(infoHdr.biSizeImage), 0, pBmpImgBuf, 34, 4);
		// another 2 members..
		// 42+4+8+8
		Logs.v("SaveRawAsBmp--1.1\n");
		System.arraycopy(int2byte(infoHdr.biClrUsed), 0, pBmpImgBuf, 38, 4);
		System.arraycopy(int2byte(infoHdr.biClrUsed), 0, pBmpImgBuf, 42, 4);
		System.arraycopy(int2byte(infoHdr.biClrUsed), 0, pBmpImgBuf, 46, 4);

		System.arraycopy(int2byte(infoHdr.biClrUsed), 0, pBmpImgBuf, 50, 4);
		System.arraycopy(int2byte(infoHdr.biClrImportant), 0, pBmpImgBuf, 54, 4);
		Logs.v("SaveRawAsBmp--2\n");
		/* 8位用调色板 1024字节 */
		for (i = 0; i < 256; i++) {
			pBmpImgBuf[58 + 4 * i] = (byte) i;
			pBmpImgBuf[59 + 4 * i] = (byte) i;
			pBmpImgBuf[60 + 4 * i] = (byte) i;
			pBmpImgBuf[61 + 4 * i] = (byte) 0;
		}

		for (int j = 0; j < dwHigh; j++) {
			System.arraycopy(pRawImgBuf, (iWidth * iHeight) - iWidth * (j + 1),
					pBmpImgBuf, 14 + 44 + 1024 + j * dwWide, dwWide);
		}

		// System.arraycopy(pRawImgBuf, 0, pBmpImgBuf, 14 + 44 + 1024, iWidth
		// * iHeight);
		mOpBmpImgLen = fileHdr.bfSize;
		Logs.v("opBmpImgLen = " + mOpBmpImgLen);
		mBmpImgBuf = new byte[(int) mOpBmpImgLen];
		System.arraycopy(pBmpImgBuf, 0, mBmpImgBuf, 0, (int) mOpBmpImgLen);

		return 0;
	}

	public static byte[] raw2WSQ(byte[] rawData) {
		return raw2WSQ(rawData, sImageAttr);
	}

	public static byte[] wsq2RAW(byte[] wsqData) {
		return wsq2RAW(wsqData, sImageAttr);
	}

	public static byte[] raw2WSQ(byte[] rawData, int[] imageAttr) {
		if (rawData == null) {
			return null;
		}
		if (imageAttr == null) {
			return null;
		}

		byte[] temp = new byte[256 * 360];

		int wsqSize = TCFP.TCFP_Raw2WSQ(rawData, rawData.length, imageAttr,
				temp, 40000, 0);
		if (wsqSize < 0 || wsqSize > temp.length) {
			Logs.e("FpImage", "wsqSize error:" + wsqSize);
			return null;
		}
		byte[] wsqData = new byte[wsqSize];
		System.arraycopy(temp, 0, wsqData, 0, wsqSize);

		return wsqData;
	}

	public static byte[] wsq2RAW(byte[] wsqData, int[] imageAttr) {
		if (wsqData == null) {
			return null;
		}
		if (imageAttr == null) {
			return null;
		}

		byte[] temp = new byte[256 * 360];

		int rawSize = TCFP.TCFP_WSQ2Raw(wsqData, wsqData.length, temp,
				imageAttr);
		if (rawSize < 0 || rawSize > temp.length) {
			Logs.e("FpImage", "rawSize error:" + rawSize);
			return null;
		}
		byte[] rawData = new byte[rawSize];
		System.arraycopy(temp, 0, rawData, 0, rawSize);

		return rawData;
	}

	public static byte[] tcFeaToGB(byte[] tcFea) {
		if (tcFea == null) {
			return null;
		}
		byte[] temp = new byte[1024];
		int[] imageAttr = { 200, 152, 363 };
		int size = TCFP.TCFP_TcMutToGb(temp, tcFea, tcFea.length, 1, imageAttr);
		if (size < 0 || size > temp.length) {
			Logs.e(TAG, "size Error! size = " + size);
			return null;
		}
		byte[] gbBytes = new byte[size];
		System.arraycopy(temp, 0, gbBytes, 0, size);

		return gbBytes;
	}

	public static byte[] gbToTcFea(byte[] gbFea) {
		if (gbFea == null) {
			return null;
		}
		byte[] temp = new byte[1024];
		int size = TCFP.TCFP_TcMutFrGb(temp, gbFea, gbFea.length);
		if (size < 0 || size > temp.length) {
			Logs.e(TAG, "size Error! size = " + size);
			return null;
		}
		byte[] tcFeaBytes = new byte[size];
		System.arraycopy(temp, 0, tcFeaBytes, 0, tcFeaBytes.length);

		return tcFeaBytes;
	}

}
